﻿using Core.WebScaner;
using HtmlAgilityPack;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Utils;
using System.Xml.Linq;

namespace WebScanner
{
    public class WebCrawler : IWebCrawler
    {
        private const string STR_SiteMapXML = "sitemap.xml";

        private enum ChangeFrequency
        {
            always,
            hourly,
            daily,
            weekly,
            monthly,
            yearly,
            never
        }

        public IEnumerable<IWebRequestProperties> DetectBrokenLinks(Uri uri)
        {
            SiteMapWebRequest siteMapWebRequest = new SiteMapWebRequest();
            HtmlPageParser htmlPageParser = new HtmlPageParser();

            var uriList = new List<WebRequestProperties>();
            uriList.Add(new WebRequestProperties() { Uri = uri });
            
            ScanSite(uri, siteMapWebRequest, htmlPageParser, uriList);

            return uriList.Where(x=>!x.StatusCode.Equals(HttpStatusCode.OK));
        }


        public void GenerateSiteMap(Uri uri)
        {
            SiteMapWebRequest siteMapWebRequest = new SiteMapWebRequest();
            HtmlPageParser htmlPageParser = new HtmlPageParser();
            var uriList = new List<WebRequestProperties>();
            uriList.Add(new WebRequestProperties() { Uri = uri });
            ScanSite(uri, siteMapWebRequest, htmlPageParser, uriList);

            SiteMapEntry siteMapEntries = new SiteMapEntry();

            Regex rgx = new Regex(@"[\w-.:_%]+");
            siteMapEntries.Title = uriList.SingleOrDefault(x=>x.Uri.Equals(uri)).Title;
            siteMapEntries.Name = "Site map";
            siteMapEntries.Url = uri.ToString();
            siteMapEntries.Entries = new List<SiteMapEntry>();

            GenerateRobotsSimapXML(uriList.Select(x => x.Uri.ToString()).ToList());

            //foreach (var uriItem in uriList)
            //{
            //    SiteMapEntry CurrEntries = siteMapEntries;
            //    StringBuilder linkSB = new StringBuilder();

            //    Match matches = rgx.Match(uriItem.Uri.ToString());
            //    int i = 0;
            //    while (matches.Success)
            //    {
            //        if (i >= 2)
            //        {
            //            linkSB.AppendFormat("{0}/", matches.Value);
            //            var entryGroup = CurrEntries.Entries.SingleOrDefault(x => x.Name == matches.Value);

            //            if ((entryGroup == null) && !String.IsNullOrWhiteSpace(matches.Value))
            //            {
            //                CurrEntries.Entries.Add(new SiteMapEntry { Name = matches.Value, Title = uriItem.Title, Url = uriItem.Uri.ToString(), Entries = new List<SiteMapEntry>() });                           
            //            }

            //            CurrEntries = CurrEntries.Entries.SingleOrDefault(x => x.Name == matches.Value);
            //        }

            //        i++;
            //        matches = matches.NextMatch();
            //    }
            //}
            
            //System.Xml.Serialization.XmlSerializer xmlSerializer = new System.Xml.Serialization.XmlSerializer(siteMapEntries.GetType());
            //StreamWriter writer = new StreamWriter(String.Format(@"{0}SiteMap\{1}-{2}.txt", PathManager.GetWebAppPath(), uri.ToString().Replace("http:", String.Empty).Replace("/", String.Empty), DateTime.Now.ToString("dd-MM-yy-hh-mm-ss")));
            //xmlSerializer.Serialize(writer, siteMapEntries);                    

        }

        private static void ScanSite(Uri uri, SiteMapWebRequest siteMapWebRequest, HtmlPageParser htmlPageParser, List<WebRequestProperties> uriList)
        {           
            while (uriList.Where(x => x.StatusCode == 0).Count() > 0)   
            {               
                siteMapWebRequest.GetContent(uriList.Where(x => x.StatusCode == 0).ToList());
                htmlPageParser.AddNewUris(uri, uriList);                
            }
        }

        private static XElement CreateItemElement(string url)
        {
            XElement itemElement = new XElement("url", new XElement("loc", url.ToLower()));


            itemElement.Add(new XElement("lastmod", DateTime.Now.ToString("yyy-MM-dd", System.Globalization.CultureInfo.InvariantCulture)));


            itemElement.Add(new XElement("changefreq", ChangeFrequency.always.ToString()));


            itemElement.Add(new XElement("priority", "0.8"));

            return itemElement;
        }

        private static void GenerateRobotsSimapXML(List<string> urls)
        {
            XDocument sitemap = new XDocument(new XDeclaration("1.0", "utf-8", "yes"),
            new XElement("urlset", XNamespace.Get("http://www.sitemaps.org/schemas/sitemap/0.9"),
                 from url in urls
                 select CreateItemElement(url)
                 )
            );

            sitemap.Save(System.AppDomain.CurrentDomain.BaseDirectory + STR_SiteMapXML);
        }
                
    }
}
